<?php

namespace Biz\service\advertisement;



use Biz\cache\advertisement\CApiCounter;
use Biz\cache\advertisement\CPosition;
use Biz\cache\advertisement\CPositionBaseInfo;
use Biz\cache\advertisement\CPositionClose;
use Biz\model\advertisement\MPosition;

trait AdCacheManagement
{

    protected $caches = null;

    public function writeFrom(): int
    {
        return CApiCounter::OP_WRITE;
    }

    public function readFrom(): int
    {
        return CApiCounter::OP_READ;
    }

    public function keyFrom(): int
    {
        return CApiCounter::OP_KEY;
    }

    public static function getAllPositionCache($ids): array
    {
        return CPositionBaseInfo::mGetItems($ids);
    }

    public function onceKey($uid, $position_id, $id)
    {
        return $this->getApiCounterTypeValue(CApiCounter::SIGN_TYPE_ONCE, $uid, $position_id, $id, $this->keyFrom());
    }

    /**
     * 获取/设置计数器的键
     * @time 2021-11-23
     */
    public function getApiCounterTypeValue($type, $uid, $position_id, $id, $from = CApiCounter::OP_READ, $date = null)
    {
        $key = null;
        $value = null;
        switch ($type) {
            case CApiCounter::SIGN_TYPE_DAY:
                $key = CApiCounter::getDayKey($uid, $position_id, $date);
                $value = $this->setHIncrValue($from, $key, $id);
                break;
            case CApiCounter::SIGN_TYPE_START:
                $key = CApiCounter::getStartKey($uid, $position_id, $date);
                $value = $this->setHIncrValue($from, $key, $id);
                break;
            case CApiCounter::SIGN_TYPE_ONCE:
                $key = CApiCounter::getOnceKey($uid, $position_id);
                $value = CApiCounter::hGet($key, $id);
                if ($from & CApiCounter::OP_WRITE) CApiCounter::hSetNx($key, $id, time());
                break;
            case CApiCounter::SIGN_TYPE_2DAYS:
                $key = CApiCounter::get2DaysKey($uid, $position_id, $id);
                $value = $this->setStringValue($from, $key, '2 day');
                break;
            case CApiCounter::SIGN_TYPE_3DAYS:
                $key = CApiCounter::get3DaysKey($uid, $position_id, $id);
                $value = $this->setStringValue($from, $key, '3 day');
                break;
            case CApiCounter::SIGN_TYPE_WEEK:
                $key = CApiCounter::getWeekKey($uid, $position_id, $id);
                $value = $this->setStringValue($from, $key, '7 day');
                break;
        }
        return ($from & CApiCounter::OP_KEY) ? $key : $value;
    }

    public function setStringValue($from, $key, $datetime = '1 day')
    {
        $value = CApiCounter::get($key);
        if ($from & CApiCounter::OP_WRITE) {
            CApiCounter::setnx($key, time());
            CApiCounter::expireAt($key, strtotime($datetime));
        }
        return $value;
    }

    public function setHIncrValue($from, $key, $hashKey)
    {
        $value = CApiCounter::hGet($key, $hashKey);
        if ($from & CApiCounter::OP_WRITE) {
            $value = CApiCounter::hIncrBy($key, $hashKey, 1);
            if ($value == 1) CApiCounter::expireAt($key, strtotime('1 day'));
        }
        return $value;
    }

    /**
     * 新用户免打扰的 key
     */
    public function notDisruptKey($uid, $position_id): string
    {
        return CApiCounter::getWholeDayKey($uid, $position_id);
    }

    /**
     * 新用户首次免打扰的 key
     */
    public function newLockKey($uid, $position_id): string
    {
        return CApiCounter::getNewDayKey($uid, $position_id);
    }

    /**
     * 每天执行一次的 key
    */
    public function lockKey($uid, $position_id): string
    {
        return CApiCounter::getWholeDayKey($uid, $position_id);
    }

    /**
     * 每次启动执行一次的 key
     */
    public function startLockKey($uid, $position_id): string
    {
        return CApiCounter::getOnceStartKey($uid, $position_id);
    }

    /**
     * 资源位调取间隔 key
     */
    public function gapLockKey($uid, $position_id): string
    {
        return CApiCounter::getGapKey($uid, $position_id);
    }

    public function lock($lockKey)
    {
        return CApiCounter::get($lockKey);
    }

    public function releaseLock($lockKey): int
    {
        return CApiCounter::del($lockKey); 
    }

    /**
     * 设置每天执行一次的 key, 自然日失效
     */
    public function setLock($lockKey, $ttl = -1)
    {
        // 输出过
        CApiCounter::set($lockKey, 1);
        //设置过期时间
        if ($ttl == -1) {
            CApiCounter::expireAt($lockKey, strtotime(date("23:59:59")));
        } else {
            CApiCounter::expire($lockKey, $ttl);
        }
    }



    /**
     * 单次启动 app 关闭标识, 启动后清空
    */
    public function startClose($uid, $position_id, $id, $sign = 'r')
    {
//        $redis = new \Redis();
//        $redis->hSet()
        $rds_key = CPositionClose::getCloseKey($uid, $position_id);
        $exists = CPositionClose::hExists($rds_key, $id);

        if ($sign == 'r') return $exists;
        if ($sign == 'w') {
            CPositionClose::hSet($rds_key, $id, time());
        }
    }

    public function dayClose($uid, $position_id, $id)
    {
        return (bool)CPositionClose::closeDay($uid, $position_id, $id);
    }

    public static function positionList($pattern = MPosition::POSITION_PATTERN_DB_LIST, $force = false)
    {
        $cache = AdPositionManagement::getConf();

        switch ($pattern) {
            case MPosition::POSITION_PATTERN_ROUTE_MAP:
                $cache = empty($cache) ? [] : array_column($cache, null, 'en_name');
                break;
            case MPosition::POSITION_PATTERN_DB_LIST:
                $cache = empty($cache) ? [] : array_column($cache, null, 'id');
                break;
            case MPosition::POSITION_PATTERN_NAME_MAP:
                $cache = empty($cache) ? [] : array_column($cache, 'title', 'id');
                break;
            case MPosition::POSITION_PATTERN_API_MAP:
                $temp = [];
                foreach ($cache as $v) {
                    $temp[$v['id']] = implode(" | ", [$v['title'], $v['id']]);
                }
                $cache = $temp;
                break;
        }

        return $cache;
    }

    public static function createAdmUser($user)
    {
        $key = CPosition::admKey();
        return CPosition::sAdd($key, $user);
    }

    public static function delAdmUser($user)
    {
        $key = CPosition::admKey();
        return CPosition::sRem($key, $user);
    }

    public static function listAdmUser()
    {
        $key = CPosition::admKey();
        return CPosition::sMembers($key);
    }

    public static function isAdmUser($user)
    {
        $key = CPosition::admKey();
        return CPosition::sisMember($key, $user);
    }
}